package com.filldream.fastboot.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.security.KeyStore;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author RickSun
 * @version 1.0
 * @data 2020-11-26 17:33
 * @description 支付基本工具类
 */
@Slf4j
public class PayUtil {

    // HTTP请求器
    private static CloseableHttpClient httpClient;
    // 请求器的配置
    private static RequestConfig requestConfig;

    /**
     * @author RickSun
     * @Description 构建map
     * @param sortedParams  加密map
     * @param keyName  尾部构建名
     * @param keyValue  尾部构建值
     **/
    public static String build(Map<String, String> sortedParams,String keyName,String keyValue){
        String build = build(sortedParams);
        build += ("&" + keyName + "=" + keyValue);
        return build;
    }

    /**
     * @author RickSun
     * @Description 构建map
     * @param sortedParams  加密map
     **/
    public static String build(Map<String, String> sortedParams) {
        StringBuilder builder = new StringBuilder();
        if (!(sortedParams instanceof TreeMap)) {
            Map<String, String> temp = new TreeMap<>();
            temp.putAll(sortedParams);
            sortedParams = temp;
        }
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            String k = entry.getKey();
            Object v = entry.getValue();
            if (StringUtils.isBlank(k) || StringUtils.isBlank(v.toString())) {
                continue;
            }
            if (builder.length() != 0) {
                builder.append("&");
            }
            builder.append(k);
            builder.append("=");
            builder.append(v);

        }
        return builder.toString();

    }

    /**
     * @author RickSun
     * @Description MD5签名加密
     * @param str  加密文本
     **/
    public static String sign(String str){
        return EncryptUtil.md5Encode(str).toUpperCase();
    }

    /**
     * @author RickSun
     * @Description 获取Request的值
     **/
    public static String getRequestData(HttpServletRequest request) throws Exception {
        String charset = getCharset(request);
        StringBuffer buffer = new StringBuffer();
        BufferedReader rd = null;
        try {
            rd = new BufferedReader(new InputStreamReader(request.getInputStream(), charset));
            String tempLine = null;
            while ((tempLine = rd.readLine()) != null) {
                buffer.append(tempLine);
            }
        } finally {
            try {
                if (rd != null) {
                    rd.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return buffer.toString().trim();
    }

    /**
     * @author RickSun
     * @Description 字符格式
     **/
    public static String getCharset(HttpServletRequest request) {
        if (request != null) {
            return request.getCharacterEncoding();
        }
        return "UTF-8";
    }

    /**
     * @author RickSun
     * @Description 证书POST请求
     * @param url 请求地址
     * @param mchId 商户ID
     * @param xmlObj xml的body
     **/
    public static String postData(String url,String mchId, String xmlObj) {
        // 加载证书
        try {
            initCert(mchId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);
        // 根据默认超时限制初始化requestConfig
        requestConfig = RequestConfig.custom()
                .setSocketTimeout(6000)
                .setConnectTimeout(6000)
                .build();
        // 设置请求器的配置
        httpPost.setConfig(requestConfig);
        try {
            HttpResponse response = null;
            try {
                response = httpClient.execute(httpPost);
            }  catch (IOException e) {
                e.printStackTrace();
            }
            HttpEntity entity = response.getEntity();
            try {
                result = EntityUtils.toString(entity, "UTF-8");
            }  catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            httpPost.abort();
        }
        return result;
    }


    /**
     * @author RickSun
     * @Description 加载双向证书
     * @param mchId 商户ID
     **/
    private static void initCert(String mchId) throws Exception {
        //证书的路径，可修改路径
        String path = "E:\\OtherSoft\\wechatpay\\WXCertUtil\\cert\\1600737490_20201201_cert\\apiclient_cert.p12";
        boolean windows = System.getProperty("os.name").toLowerCase().contains("windows");
        if(!windows){
            path = "/root/code/cert/apiclient_cert.p12";
        }

        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 读取本机存放的PKCS12证书文件
//        FileInputStream instream = new FileInputStream(new File(path));
        //读取静态资源
        InputStream instream = FileIOUtil.getPathFile("cert/apiclient_cert.p12");
        try {
            // 指定PKCS12的密码(商户ID)
            keyStore.load(instream, mchId.toCharArray());
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts
                .custom()
                .loadKeyMaterial(keyStore, mchId.toCharArray())
                .build();
        // 指定TLS版本
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext, new String[] { "TLSv1" }, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        // 设置httpclient的SSLSocketFactory
        httpClient = HttpClients
                .custom()
                .setSSLSocketFactory(sslsf)
                .build();
    }

}
